import re
from typing import List
from src.db import dbs, dbm
from typing import Annotated
from pydantic import BaseModel
from src.core.variables.constant import *
from src.core.variables.function import *
from src.core.variables.exception import *
from pydantic import Field, AfterValidator, model_validator


# 自定义类型验证器
class _Validate:
    @staticmethod
    def on_empty(v: str) -> str:
        if not v.strip():
            if v not in [""]:
                log.ERROR(f"字段值不能为空: {v}")
                raise ValueError(f"字段值不能为空")
        return v

    @staticmethod
    def username(v: str) -> str:
        if not re.fullmatch(PATTERN.USERNAME, v):
            raise ValueError("用户名只能包含字母、数字和下划线(3-20位)")
        if v.lower() in ["admin", "root", "administrator"]:
            raise ValueError("该用户名被保留，请选择其他用户名")
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            if (
                db_session.query(dbs.sys_default.User)
                .filter(dbs.sys_default.User.username == v)
                .first()
            ):
                raise ValueError("用户名已存在！")
            return v

    @staticmethod
    def password(v: str) -> str:
        print(v, any(c.isupper() for c in v))
        if not any(c.isupper() for c in v):
            raise ValueError("密码必须包含至少一个大写字母")
        if not any(c.islower() for c in v):
            raise ValueError("密码必须包含至少一个小写字母")
        if not any(c.isdigit() for c in v):
            raise ValueError("密码必须包含至少一个数字")
        return v

    @staticmethod
    def email(v: str) -> str:
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            if (
                db_session.query(dbs.sys_default.User)
                .filter(dbs.sys_default.User.email == v)
                .first()
            ):
                raise ValueError("邮件被使用！")
            return v

    @staticmethod
    def phone(v: str) -> str:
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            if (
                db_session.query(dbs.sys_default.User)
                .filter(dbs.sys_default.User.phone == v)
                .first()
            ):
                raise ValueError("手机号被使用！")
            return v

    @staticmethod
    def roles(v: list) -> list:
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            for i in v:
                db_result = (
                    db_session.query(dbs.sys_default.Role)
                    .filter(dbs.sys_default.Role.name == i)
                    .all()
                )
                if len(db_result) == 0:
                    raise ValueError(f"【{i}】角色不存在！")
                elif len(db_result) > 1:
                    raise ValueError(f"存在名称重复的角色，请检查角色配置列表！")
                elif len(db_result) == 1:
                    continue
                else:
                    raise ValueError(f"角色库数据异常，请联系管理员！")
            return v

    @staticmethod
    def uid(v: list) -> list:
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            db_result = (
                db_session.query(dbs.sys_default.User)
                .filter(dbs.sys_default.User.uid == v)
                .all()
            )
            if len(db_result) == 0:
                raise ValueError(f"用户不存在！")
            elif len(db_result) > 1:
                log.ERROR(f"存在名称重复的用户，请检查数据库！")
                raise ValueError(f"存在名称重复的用户，请检查用户配置列表！")
            return v


class signup_schema(BaseModel):
    """用户注册"""

    username: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.username)
    ] = Field(..., description="用户名(3-20位字母数字下划线)")
    password: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.password)
    ] = Field(..., pattern=PATTERN.PASSWORD, description="密码(至少8位)")
    email: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.email)
    ] = Field(..., pattern=PATTERN.EMAIL, description="电子邮件")
    phone: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.phone)
    ] = Field(..., pattern=PATTERN.PHONE, description="手机号")
    roles: Annotated[
        List[str], AfterValidator(_Validate.on_empty), AfterValidator(_Validate.roles)
    ] = Field(..., description="角色")


class login_schema(BaseModel):
    """用户登录"""

    username: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="用户名"
    )
    password: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., pattern=PATTERN.PASSWORD, description="密码"
    )


class remove_user_schema(BaseModel):
    """删除用户"""

    uid: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.uid)
    ] = Field(..., description="用户ID")


class user_list_schema(BaseModel):
    """用户列表"""

    ...


class user_info_schema(BaseModel):
    """用户信息"""

    uid: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.uid)
    ] = Field(..., description="用户ID")


class user_update_schema(BaseModel):
    """用户信息更新"""

    uid: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.uid)
    ] = Field(..., description="用户ID")
    username: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.username)
    ] = Field(..., description="用户名(3-20位字母数字下划线)")
    password: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.password)
    ] = Field(..., pattern=PATTERN.PASSWORD, description="密码(至少8位)")
    email: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.email)
    ] = Field(..., pattern=PATTERN.EMAIL, description="电子邮件")
    phone: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.phone)
    ] = Field(..., pattern=PATTERN.PHONE, description="手机号")
    roles: Annotated[
        List[str], AfterValidator(_Validate.on_empty), AfterValidator(_Validate.roles)
    ] = Field(..., description="角色")


class update_passwd_schema(BaseModel):
    """用户密码更新"""

    uid: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.uid)
    ] = Field(..., description="用户ID")
    old_password: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., pattern=PATTERN.PASSWORD, description="旧密码(至少8位)"
    )
    new_password: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.password)
    ] = Field(..., pattern=PATTERN.PASSWORD, description="新密码(至少8位)")

    @model_validator(mode="after")
    def V_old_passwd(cls, values):
        """校验stype与app_id是否匹配"""
        old_passwd = values.old_password
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session
            db_session: scoped_session
            db_result = (
                db_session.query(dbs.sys_default.User)
                .filter(dbs.sys_default.User.uid == values.uid)
                .first()
            )
            if db_result:
                if not db_result.password == ENCRYPTION(old_passwd):
                    raise MAIN_VALUE_ERROR_FUNC(
                        loc=("old_password",),
                        msg="旧密码错误！",
                        value=values,
                        model_name=__class__.__name__,
                    )
            else:
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("uid",),
                    msg="用户不存在！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values
